﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using UnityEditor;
using UnityEngine;

internal class Xbox360Utils
{
    public static void DeployKinectResources(string xedkPath, string installPath)
    {
        if (PlayerSettings.xboxDeployKinectResources)
        {
            FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/Databases/Database.xmplr"), Path.Combine(installPath, "Database.xmplr"));
            FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/Databases/NuiIdentity.bin.be"), Path.Combine(installPath, "NuiIdentity.bin.be"));
        }
        if (PlayerSettings.xboxEnableSpeech)
        {
            if ((PlayerSettings.xboxSpeechDB & 1) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp1033"), Path.Combine(installPath, "nuisp1033"));
            }
            if ((PlayerSettings.xboxSpeechDB & 2) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp3084"), Path.Combine(installPath, "nuisp3084"));
            }
            if ((PlayerSettings.xboxSpeechDB & 4) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp2057"), Path.Combine(installPath, "nuisp2057"));
            }
            if ((PlayerSettings.xboxSpeechDB & 8) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp2058"), Path.Combine(installPath, "nuisp2058"));
            }
            if ((PlayerSettings.xboxSpeechDB & 0x10) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp1041"), Path.Combine(installPath, "nuisp1041"));
            }
            if ((PlayerSettings.xboxSpeechDB & 0x20) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp1036"), Path.Combine(installPath, "nuisp1036"));
            }
            if ((PlayerSettings.xboxSpeechDB & 0x40) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp3082"), Path.Combine(installPath, "nuisp3082"));
            }
            if ((PlayerSettings.xboxSpeechDB & 0x80) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp1031"), Path.Combine(installPath, "nuisp1031"));
            }
            if ((PlayerSettings.xboxSpeechDB & 0x100) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp1040"), Path.Combine(installPath, "nuisp1040"));
            }
            if ((PlayerSettings.xboxSpeechDB & 0x200) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp3081"), Path.Combine(installPath, "nuisp3081"));
            }
            if ((PlayerSettings.xboxSpeechDB & 0x400) != 0)
            {
                FileUtil.CopyFileOrDirectory(Path.Combine(xedkPath, "redist/xbox/NaturalInput/speech/nuisp1046"), Path.Combine(installPath, "nuisp3081"));
            }
        }
    }

    public static bool IsTitleIdValid(string titleId)
    {
        return Regex.IsMatch(titleId, "^[A-F0-9]{8}$");
    }

    public static bool LinkMonoAssembliesParallel(string sourceAssembliesFolder, string targetCrossCompiledASMFolder, string installPath, BuildOptions options)
    {
        BuildTarget target = BuildTarget.XBOX360;
        sourceAssembliesFolder = Path.Combine(Directory.GetCurrentDirectory(), sourceAssembliesFolder);
        targetCrossCompiledASMFolder = Path.Combine(Directory.GetCurrentDirectory(), targetCrossCompiledASMFolder);
        long baseAddress = 0x8000000L;
        long num2 = 0x10000L;
        int workerThreads = 1;
        int completionPortThreads = 1;
        ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
        List<JobLinkMonoAssemblies> list = new List<JobLinkMonoAssemblies>();
        List<ManualResetEvent> list2 = new List<ManualResetEvent>();
        foreach (string str in Directory.GetFiles(sourceAssembliesFolder))
        {
            if (Path.GetExtension(str) == ".dll")
            {
                JobLinkMonoAssemblies item = new JobLinkMonoAssemblies(BuildPipeline.GetBuildToolsDirectory(target), sourceAssembliesFolder, str, targetCrossCompiledASMFolder);
                list.Add(item);
                list2.Add(item.m_doneEvent);
                ThreadPool.QueueUserWorkItem(new WaitCallback(item.ThreadPoolCallback));
            }
        }
        ManualResetEvent[] waitHandles = list2.ToArray();
        EditorUtility.DisplayProgressBar("Building Player", "Generating native code.", 0.96f);
        bool flag = WaitHandle.WaitAll(waitHandles, 0x493e0);
        foreach (JobLinkMonoAssemblies assemblies2 in list)
        {
            if (assemblies2.m_Exception != null)
            {
                UnityEngine.Debug.LogError(string.Format("Assembly conversion job {0} failed.\n{1}", assemblies2.m_inputName, assemblies2.m_Exception.ToString()));
                flag = false;
            }
        }
        if (flag)
        {
            bool generatePdb = true;
            foreach (JobLinkMonoAssemblies assemblies3 in list)
            {
                long num6 = LinkMonoAssemblyStep2(assemblies3.m_buildingDataFolder, assemblies3.m_inputName, assemblies3.m_outputDir, installPath, baseAddress, generatePdb);
                baseAddress += ((num6 + num2) + 0xffffL) & -65536L;
            }
        }
        return flag;
    }

    internal static void LinkMonoAssemblyStep1(string crossPlatformToolsFolder, string buildingDataFolder, string inputName, string outputDir)
    {
        string str = Path.Combine(outputDir, Path.GetFileName(inputName));
        string path = Path.Combine(outputDir, str) + ".o";
        Process process = new Process {
            StartInfo = { FileName = Path.Combine(crossPlatformToolsFolder, "ppc64-linux-as.exe") }
        };
        string[] textArray1 = new string[] { "\"", str, ".s\" -o \"", path, "\"" };
        process.StartInfo.Arguments = string.Concat(textArray1);
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.WorkingDirectory = outputDir;
        process.Start();
        process.WaitForExit();
        if ((process.ExitCode != 0) || !File.Exists(path))
        {
            throw new System.Exception("Failed Assembling " + str);
        }
        string str3 = Path.Combine(outputDir, str) + ".obj";
        Process process2 = new Process {
            StartInfo = { FileName = Path.Combine(crossPlatformToolsFolder, "Elf2Coff.exe") }
        };
        string[] textArray2 = new string[] { "\"", str, ".o\" \"", str, ".obj\"  \"", str, ".def\"" };
        process2.StartInfo.Arguments = string.Concat(textArray2);
        process2.StartInfo.CreateNoWindow = true;
        process2.StartInfo.UseShellExecute = false;
        process2.StartInfo.WorkingDirectory = outputDir;
        process2.Start();
        process2.WaitForExit();
        if ((process2.ExitCode != 0) || !File.Exists(str3))
        {
            throw new System.Exception("Failed processing assemblies " + str);
        }
    }

    internal static long LinkMonoAssemblyStep2(string buildingDataFolder, string inputName, string outputDir, string installPath, long baseAddress, bool generatePdb)
    {
        string str = Path.Combine(outputDir, Path.GetFileName(inputName));
        long length = 0L;
        string str2 = str + ".xex";
        string sourceFileName = str + ".def";
        string environmentVariable = Environment.GetEnvironmentVariable("XEDK");
        if (environmentVariable.Length == 0)
        {
            throw new System.Exception("XEDK environment variable missing. Please install the XDK");
        }
        string xboxImageXexFilePath = PlayerSettings.xboxImageXexFilePath;
        if (!Path.IsPathRooted(xboxImageXexFilePath))
        {
            xboxImageXexFilePath = Path.Combine(Directory.GetCurrentDirectory(), xboxImageXexFilePath);
        }
        bool flag = (PlayerSettings.xboxImageXexFilePath.Length > 0) && File.Exists(xboxImageXexFilePath);
        object[] args = new object[] { Path.Combine(environmentVariable, @"lib\xbox\oldnames.lib"), Path.Combine(environmentVariable, @"lib\xbox\libcmt.lib"), Path.Combine(environmentVariable, @"lib\xbox\xapilib.lib"), Path.Combine(environmentVariable, @"lib\xbox\xboxkrnl.lib") };
        string str6 = string.Format(" \"{0}\" \"{1}\" \"{2}\" \"{3}\" ", args);
        string str7 = Path.Combine(outputDir, "dummyEntry");
        string str8 = "int __cdecl _DllMainCRTStartup(void*,unsigned long,void*) { return 1; }\n";
        StreamWriter writer = new StreamWriter(str7 + ".cpp");
        writer.WriteLine(str8);
        writer.Close();
        Process process = new Process {
            StartInfo = { FileName = Path.Combine(environmentVariable, @"bin\win32\cl.exe"), Arguments = "/TP dummyEntry.cpp /link /dll ", UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = outputDir }
        };
        process.Start();
        process.WaitForExit();
        if (!File.Exists(str7 + ".obj"))
        {
            throw new System.Exception("Failed generating native code entry point " + str);
        }
        bool flag2 = true;
        string str9 = !flag2 ? string.Empty : ":NO";
        string str10 = str2 + ".raw";
        process = new Process {
            StartInfo = { FileName = Path.Combine(environmentVariable, @"bin\win32\link.exe") }
        };
        object[] objArray2 = new object[] { baseAddress, str, str10, str7, str9 };
        process.StartInfo.Arguments = string.Format(" /XEX{4} /INCREMENTAL:NO /NOLOGO /DLL /ENTRY:_DllMainCRTStartup /BASE:{0} \"{1}.obj\" /OUT:\"{2}\" /DEF:\"{1}.def\" \"{3}.obj\" ", objArray2);
        if (flag)
        {
            ProcessStartInfo info1 = process.StartInfo;
            info1.Arguments = info1.Arguments + string.Format(" /XEXCONFIG:\"{0}\" ", xboxImageXexFilePath);
        }
        ProcessStartInfo startInfo = process.StartInfo;
        startInfo.Arguments = startInfo.Arguments + str6;
        if (generatePdb)
        {
            string str11 = Path.Combine(installPath, "/Media/Managed/" + Path.GetFileName(inputName));
            ProcessStartInfo info3 = process.StartInfo;
            info3.Arguments = info3.Arguments + string.Format(" /DEBUG /PDB:\"{0}.pdb\" /PDBALTPATH:\"{1}.pdb\" ", str, str11);
        }
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.WorkingDirectory = outputDir;
        process.Start();
        process.WaitForExit();
        if ((process.ExitCode != 0) || !File.Exists(Path.Combine(outputDir, str10)))
        {
            throw new System.Exception("Failed linking " + str);
        }
        FileStream stream = File.Open(Path.Combine(outputDir, str10), FileMode.Open);
        if (Stream.Null == stream)
        {
            throw new System.Exception("Failed calculate base address for " + str10);
        }
        length = stream.Length;
        stream.Close();
        if (flag2)
        {
            process = new Process {
                StartInfo = { FileName = Path.Combine(environmentVariable, @"bin\win32\imagexex.exe"), Arguments = string.Format("/nologo /format:compressed /in:\"{0}\" /out:\"{1}\"", str10, str2) }
            };
            if (flag)
            {
                ProcessStartInfo info4 = process.StartInfo;
                info4.Arguments = info4.Arguments + string.Format(" /CONFIG:\"{0}\" ", xboxImageXexFilePath);
            }
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.WorkingDirectory = outputDir;
            process.Start();
            process.WaitForExit();
            if ((process.ExitCode != 0) || !File.Exists(Path.Combine(outputDir, str2)))
            {
                throw new System.Exception("Failed converting library image! Args: " + process.StartInfo.Arguments);
            }
            length += 0x10000L;
        }
        else
        {
            File.Copy(str10, str2);
        }
        File.Copy(str2, Path.Combine(buildingDataFolder, Path.GetFileName(str2)));
        File.Copy(sourceFileName, Path.Combine(buildingDataFolder, Path.GetFileName(sourceFileName)));
        if (generatePdb)
        {
            string str12 = str + ".pdb";
            File.Copy(str12, Path.Combine(buildingDataFolder, Path.GetFileName(str12)));
            string str13 = str + ".xdb";
            File.Copy(str13, Path.Combine(buildingDataFolder, Path.GetFileName(str13)));
        }
        return length;
    }

    public class JobLinkMonoAssemblies
    {
        public string m_buildingDataFolder;
        public string m_crossPlatformToolsFolder;
        public ManualResetEvent m_doneEvent = new ManualResetEvent(false);
        public System.Exception m_Exception;
        public string m_inputName;
        public string m_outputDir;

        public JobLinkMonoAssemblies(string crossPlatformToolsFolder, string buildingDataFolder, string inputName, string outputDir)
        {
            this.m_crossPlatformToolsFolder = crossPlatformToolsFolder;
            this.m_buildingDataFolder = buildingDataFolder;
            this.m_inputName = inputName;
            this.m_outputDir = outputDir;
        }

        public void ThreadPoolCallback(object threadContext)
        {
            try
            {
                Xbox360Utils.LinkMonoAssemblyStep1(this.m_crossPlatformToolsFolder, this.m_buildingDataFolder, this.m_inputName, this.m_outputDir);
            }
            catch (System.Exception exception)
            {
                this.m_Exception = exception;
            }
            this.m_doneEvent.Set();
        }
    }
}

